home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / UUPC3 / (UUPC__) / DCPFPKT.C < prev    next >
Text File  |  1992-02-10  |  6KB  |  319 lines

  1. /* $Header: fio.c,v 1.20 85/04/30 12:57:32 rick Exp $ */
  2. /*    %M%    %I%    %E%    (Mathematisch Centrum)    */
  3.  
  4. /*
  5.  * flow control protocol.
  6.  *
  7.  * This protocol relies on flow control of the data stream.
  8.  * It is meant for working over links that can (almost) be
  9.  * guaranteed to be errorfree, specifically X.25/PAD links.
  10.  * A sumcheck is carried out over a whole file only. If a
  11.  * transport fails the receiver can request retransmission(s).
  12.  * This protocol uses a 7-bit datapath only, so it can be
  13.  * used on links that are not 8-bit transparent.
  14.  *
  15.  * When using this protocol with an X.25 PAD:
  16.  * Although this protocol uses no control chars except CR,
  17.  * control chars NULL and ^P are used before this protocol
  18.  * is started; since ^P is the default char for accessing
  19.  * PAD X.28 command mode, be sure to disable that access
  20.  * (PAD par 1). Also make sure both flow control pars
  21.  * (5 and 12) are set. The CR used in this proto is meant
  22.  * to trigger packet transmission, hence par 3 should be 
  23.  * set to 2; a good value for the Idle Timer (par 4) is 10.
  24.  * All other pars should be set to 0.
  25.  * Normally a calling site will take care of setting the
  26.  * local PAD pars via an X.28 command and those of the remote
  27.  * PAD via an X.29 command, unless the remote site has a
  28.  * special channel assigned for this protocol with the proper
  29.  * par settings.
  30.  *
  31.  * Author: Piet Beertema, CWI, Amsterdam, Sep 1984
  32.  * Adapted to uupc 3.0 and THINK C 4.0 by Dave Platt, Jul 1991
  33.  */
  34.  
  35. /*
  36.             Portions Copyright ⌐ David Platt, 1992, 1991.  All Rights Reserved
  37.             Worldwide.
  38. */
  39.  
  40. #include "dcp.h"
  41.  
  42. #define PKTSIZE   128
  43.  
  44. #ifndef MAXMSGLEN
  45. #define MAXMSGLEN    BUFSIZ
  46. #endif MAXMSGLEN
  47.  
  48. static int chksum;
  49.  
  50. int fopenpk()
  51. {
  52.     flowcontrol(TRUE);
  53.     pktsize = PKTSIZE;
  54.     msgtime = MSGTIME;
  55.     zzz(2); /* Give peer time to perform corresponding port setup */
  56.     return OK;
  57. }
  58.  
  59. fclosepk()
  60. {
  61.     flowcontrol(FALSE);
  62.     return OK;
  63. }
  64.  
  65. fwrmsg(char *str, boolean nowait)
  66. {
  67.     register char *s;
  68.     char bufr[MAXMSGLEN];
  69.  
  70.     s = bufr;
  71.     while (*str)
  72.         *s++ = *str++;
  73.     if (*(s-1) == '\n')
  74.         s--;
  75.     *s++ = '\r';
  76.     (void) swrite(bufr, s - bufr);
  77.     return OK;
  78. }
  79.  
  80. frdmsg(register char *str, int *bytes)
  81. {
  82.     register char *smax;
  83.     char *base = str;
  84.  
  85.     smax = str + MAXPACK - 1;
  86.     for (;;) {
  87.         if (sread(str, 1, msgtime) <= 0)
  88.             goto msgerr;
  89.         if (*str == '\r')
  90.             break;
  91.         if (*str < ' ')
  92.             continue;
  93.         if (str++ >= smax)
  94.             goto msgerr;
  95.     }
  96.     *str = '\0';
  97.     *bytes = strlen(base) + 1;
  98.     return OK;
  99. msgerr:
  100.     return FAILED;
  101. }
  102.  
  103.  
  104. fgetpkt(char *packet, int *bytes)
  105. {
  106.     register char *op, c, *ip;
  107.     register int sum, len, nl, left;
  108.     char buf[5], tbuf[MAXPACK];
  109.     int i, tleft, sready, slept;
  110.     static char special = 0;
  111.     
  112.     left = pktsize;
  113.     op = packet;
  114.     sum = chksum;
  115.     tleft = 0;
  116.  
  117.     do {
  118.         if (tleft == 0) {
  119.             ip = tbuf;
  120.             sready = savail();
  121.             if (sready > MAXPACK) {
  122.                 sready = MAXPACK;
  123.             }
  124.             if (sready > left) {
  125.                 sready = left;
  126.             } else if (sready == 0) {
  127.                 sready = 1;
  128.             }
  129.             len = sread(ip, sready, msgtime);
  130.             if (len == 0) {
  131.                 printmsg(0, "Timeout occurred while reading data");
  132.                 return FAILED; /* fail if timed out */
  133.             }
  134.             tleft = len;
  135.         }
  136.         if ((*ip &= 0177) >= '\172') {
  137.             if (special) {
  138.                 special = 0;
  139.                 if (*ip++ != '\176') {
  140.                     printmsg(0, "End-of-file checksum sequence garbled");
  141.                     goto dcorr;
  142.                 }
  143.                 tleft--;
  144.                 if (tleft > 0) {
  145.                     if (tleft > 5) tleft = 5;
  146.                     memcpy(buf, ip, tleft);
  147.                     len = tleft;
  148.                 } else {
  149.                     len = 0;
  150.                 }
  151.                 while (len < 5) {
  152.                     i = sread(&buf[len], 5 - len, msgtime);
  153.                     if (i == 0) {
  154.                         len = FAILED;
  155.                         printmsg(0, "Timeout occurred while reading checksum");
  156.                         goto dcorr;
  157.                     }
  158.                     len += i;
  159.                 }
  160.                 if (buf[4] != '\r')
  161.                     goto dcorr;
  162.                 sscanf(buf, "%4x", &chksum);
  163.                 if (chksum == sum) {
  164.                     *bytes = packet - op; /* return negative count to signal EOF */
  165.                     remote_stats.breceived -= *bytes;
  166.                     return OK;
  167.                 } else {
  168.                     printmsg(0, "Checksum mismatch, told %04x, calc %04x", chksum, sum);
  169.                     *bytes = op - packet;
  170.                     remote_stats.breceived -= *bytes;
  171.                     fsendresp(RETRY);
  172.                     return 'R';
  173.                 }
  174.             }
  175.             special = *ip++;
  176.         } else {
  177.             if (*ip < '\040') {
  178.                 /* error: shouldn't get control chars */
  179.                 printmsg(0, "Received a control character (shouldn't have!)");
  180.                 goto dcorr;
  181.             }
  182.             switch (special) {
  183.             case 0:
  184.                 c = *ip++;
  185.                 break;
  186.             case '\172':
  187.                 c = *ip++ - 0100;
  188.                 break;
  189.             case '\173':
  190.                 c = *ip++ + 0100;
  191.                 break;
  192.             case '\174':
  193.                 c = *ip++ + 0100;
  194.                 break;
  195.             case '\175':
  196.                 c = *ip++ + 0200;
  197.                 break;
  198.             case '\176':
  199.                 c = *ip++ + 0300;
  200.                 break;
  201.             }
  202.             *op++ = c;
  203.             left --;
  204.             if (sum & 0x8000) {
  205.                 sum <<= 1;
  206.                 sum++;
  207.             } else
  208.                 sum <<= 1;
  209.             sum += c & 0377;
  210.             sum &= 0xffff;
  211.             special = 0;
  212.         }
  213.         tleft--;
  214.     } while (left > 0);
  215.     *bytes = pktsize;
  216.     chksum = sum;
  217.     remote_stats.breceived += pktsize;
  218.     return OK;
  219. dcorr:
  220.     printmsg (0, "Data corrupted, skipping to EOF");
  221.     while (sread(tbuf, 1, msgtime) > 0) {
  222.         /* spin really fast */
  223.     }
  224.     fsendresp(RETRY);
  225.     return 'R';
  226. }
  227.  
  228. fsendpkt(char *ip, int len, int flag)
  229. {
  230.     register char *op;
  231.     register int sum, nl;
  232.     int ret;
  233.     char obuf[MAXPACK * 2];
  234.     op = obuf;
  235.     nl = 0;
  236.     sum = chksum;
  237.     if (flag) {
  238.         len = strlen(ip)+1;
  239.     } else {
  240.         if (len == 0) return;
  241.     }
  242.     remote_stats.bsent += len;
  243.     do {
  244.         if (sum & 0x8000) {
  245.             sum <<= 1;
  246.             sum++;
  247.         } else
  248.             sum <<= 1;
  249.         sum += *ip & 0377;
  250.         sum &= 0xffff;
  251.         if (*ip & 0200) {
  252.             *ip &= 0177;
  253.             if (*ip < 040) {
  254.                 *op++ = '\174';
  255.                 *op++ = *ip++ + 0100;
  256.             } else
  257.             if (*ip <= 0171) {
  258.                 *op++ = '\175';
  259.                 *op++ = *ip++;
  260.             }
  261.             else {
  262.                 *op++ = '\176';
  263.                 *op++ = *ip++ - 0100;
  264.             }
  265.             nl += 2;
  266.         } else {
  267.             if (*ip < 040) {
  268.                 *op++ = '\172';
  269.                 *op++ = *ip++ + 0100;
  270.                 nl += 2;
  271.             } else
  272.             if (*ip <= 0171) {
  273.                 *op++ = *ip++;
  274.                 nl++;
  275.             } else {
  276.                 *op++ = '\173';
  277.                 *op++ = *ip++ - 0100;
  278.                 nl += 2;
  279.             }
  280.         }
  281.     } while (--len > 0);
  282.     chksum = sum;
  283.     ret = swrite(obuf, nl);
  284.     return ret == nl ? nl : ret < 0 ? 0 : -ret;
  285. }
  286.  
  287. int ffilepkt()
  288. {
  289.     chksum = 0xffff;
  290.     return 0;
  291. }
  292.  
  293. feofpkt()
  294. {
  295.     char ibuf[MAXMSGLEN], ack;
  296.     int len;
  297.     sprintf(ibuf, "\176\176%04x", chksum);
  298.     fwrmsg(ibuf, FALSE);
  299.     ack = 'A';
  300.     if (frdmsg(ibuf, &len) != FAILED) {
  301.         ack = ibuf[0];
  302.     }
  303.     return ack;
  304. }
  305.  
  306. int fsendresp(state)
  307. int state;
  308. {
  309.     char spacket[64];
  310.     switch (state) {
  311.      case OK:
  312.         return (fwrmsg("G", FALSE));
  313.      case RETRY:
  314.         return (fwrmsg("R", FALSE));
  315.      default:
  316.         return (fwrmsg("Q", FALSE));
  317.     }
  318. }
  319.